Skip to content

Enforce single global current/next cue across all shows#5

Merged
jstarpl merged 1 commit intomainfrom
copilot/ensure-single-current-next-cue
Mar 27, 2026
Merged

Enforce single global current/next cue across all shows#5
jstarpl merged 1 commit intomainfrom
copilot/ensure-single-current-next-cue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 27, 2026

currentCueId and nextCueId were per-show with no cross-show exclusivity. Setting a cue as current or next in one show had no effect on other shows, allowing multiple concurrent current/next pointers application-wide.

Changes

  • assignShowCuePointer — wrapped in a transaction; when assigning a non-null pointer, clears the same field in all other shows and publishes show.currentCueChanged / show.nextCueChanged events for each cleared show before publishing the target show's event
  • takeShow — single-pass loop over other shows clears currentCueId unconditionally (take always produces a new current cue) and clears nextCueId only when a non-null following cue is being assigned; saves all affected rows in one call within the existing transaction
  • resetShow — unchanged; clearing a single show's pointers doesn't violate global uniqueness

@jstarpl
Copy link
Copy Markdown
Owner

jstarpl commented Mar 27, 2026

@copilot review

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 27, 2026

@copilot review

Here's my review of the changes (commit c8873d2):

What changed — Only src/server/services/show-service.ts was modified:

  • assignShowCuePointer: Now wrapped in a transaction. When setting a non-null pointer, it loads all other shows, clears the same field in any that have it set (also clearing currentCueTakenAt when the field is currentCueId), saves them, then publishes show.currentCueChanged / show.nextCueChanged events for each cleared show before publishing the event for the target show. Clearing a pointer (setting to null) doesn't touch other shows, which is correct — no global invariant is violated when clearing.

  • takeShow: A single pass over all other shows clears currentCueId unconditionally (a take always produces a new non-null current cue) and clears nextCueId only when a non-null followingCueId is being assigned (global uniqueness of the next pointer is only relevant when a cue actually becomes next). All affected rows are saved in one call inside the existing transaction, then cleared events are published before the target show's update events.

  • resetShow: Unchanged — clearing a single show's pointers doesn't introduce a duplicate, so no cross-show work is needed.

Correctness notes:

  • All DB mutations (clearing other shows + writing the target show) are inside the same transaction, so a mid-operation failure leaves no partial state.
  • Realtime events for cleared shows use the cleared show's own showId as the key, so clients subscribed to those shows receive the invalidation signal correctly via the existing showEvents bus.
  • entityId?: string is optional in ShowEvent, so passing undefined for cleared shows is type-correct and consistent with other clear-type events in the codebase (e.g., resetShow).
  • When followingCueId is null (last cue taken), other shows' nextCueId is intentionally not cleared — no cue is becoming next, so the global-uniqueness invariant isn't triggered.

No issues found. The implementation is minimal, atomic, and correctly propagates realtime events to all affected clients.

Copilot AI requested a review from jstarpl March 27, 2026 19:51
@jstarpl jstarpl merged commit c7ad4e5 into main Mar 27, 2026
1 check passed
@jstarpl jstarpl deleted the copilot/ensure-single-current-next-cue branch March 27, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants